package com.vercon.otamirror.utils.helper;

import java.util.concurrent.TimeUnit;

import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;

/**
 * @author fighter_lee
 * @date 2018/7/27
 */
public class RxTime {

    private ICondition mCondition;

    public interface ICondition {
        boolean onConditionComplete();
    }

    private long mPeriod = 1 * 1000;
    private long mTimeout = 5 * 1000;

    public long getMinTime() {
        return minTime;
    }

    public RxTime setMinTime(long minTime) {
        this.minTime = minTime;
        return this;
    }

    private long minTime = 0;

    public static RxTime newInstance() {
        return new RxTime();
    }

    public RxTime setPeriod(long period) {
        this.mPeriod = period;
        return this;
    }

    public RxTime setTimeout(long timeout) {
        this.mTimeout = timeout;
        return this;
    }

    public RxTime setICondition(ICondition iCondition) {
        this.mCondition = iCondition;
        return this;
    }

    public interface IEnqueueListener {
        void onComplete();

        void onTimeOut();
    }

    public void enqueue(boolean callbackOnMainThread, IEnqueueListener iEnqueueListener) {
        Observable<Long> observable = Observable.interval(mPeriod, TimeUnit.MILLISECONDS)
                .observeOn(Schedulers.io())
                .subscribeOn(Schedulers.io());
        final Disposable[] dd = new Disposable[1];
        observable.subscribe(new Observer<Long>() {
            @Override
            public void onSubscribe(Disposable d) {
                dd[0] = d;
            }

            @Override
            public void onNext(Long aLong) {
                long time = (aLong + 1) * mPeriod;
                if (time > minTime) {
                    if (mCondition != null) {
                        if (mCondition.onConditionComplete()) {
                            Observable.just(1)
                                    .subscribeOn(callbackOnMainThread ? AndroidSchedulers.mainThread() : Schedulers.io())
                                    .doOnNext(integer -> iEnqueueListener.onComplete()).subscribe();
                            dd[0].dispose();
                            return;
                        }
                    }
                }
                if (time > mTimeout) {
                    Observable.just(1)
                            .subscribeOn(callbackOnMainThread ? AndroidSchedulers.mainThread() : Schedulers.io())
                            .doOnNext(integer -> iEnqueueListener.onTimeOut()).subscribe();
                    dd[0].dispose();
                    return;
                }
            }

            @Override
            public void onError(Throwable e) {
                e.printStackTrace();
            }

            @Override
            public void onComplete() {

            }
        });
    }

    public void execute() {
        Observable<Long> observable = Observable.interval(0, mPeriod, TimeUnit.MILLISECONDS)
                .observeOn(Schedulers.io())
                .subscribeOn(Schedulers.io());
        final Disposable[] dd = new Disposable[1];
        observable.blockingSubscribe(new Observer<Long>() {
            @Override
            public void onSubscribe(Disposable d) {
                dd[0] = d;
            }

            @Override
            public void onNext(Long aLong) {
                long time = (aLong + 1) * mPeriod;
                if (time > minTime) {
                    if (mCondition != null) {
                        if (mCondition.onConditionComplete()) {
                            dd[0].dispose();
                            return;
                        }
                    }
                }
                if (time > mTimeout) {
                    dd[0].dispose();
                    return;
                }
            }

            @Override
            public void onError(Throwable e) {
                e.printStackTrace();
            }

            @Override
            public void onComplete() {
            }
        });
    }
}
